#pragma once

#include "GfxObject.h"
#include "BoundingBox.h"

namespace mgfx
{
	typedef int TextureID;

	struct VertexParticle;

	struct ParticleSystemDesc
	{
		ParticleSystemDesc() { ZeroMemory(this, sizeof(ParticleSystemDesc)); }
		void initDefault();

		uint NumParticles;
		float WrapAroundTimeMs; // 0 means all particles emitted at once

		float MinInitialSpeed, MaxInitialSpeed;
		float MinInitialSize, MaxInitialSize;
		float MinLifeTimeMs, MaxLifeTimeMs;

		float MaxInitialPositionDeviation;

		bool RestrictedMoveDir;
		XMFLOAT3 InitialMoveDir;
		//float MaxInitialMoveDirDeviation;

		XMFLOAT3 Acceleration;
		float SizeChangeSpeed;

		XMCOLOR Color;

		TextureID Texture;
	};
	
	class ParticleSystem : public GfxObject
	{
	public:
		void init(const ParticleSystemDesc & desc);
		void deinit();
		void update(float dt);

		ParticleSystemDesc Desc;

		struct Particle
		{
			XMFLOAT3 Position;
			XMFLOAT3 Velocity;
			float SpawnTime;
			float LifeTimeMs;
			float Size;
		};

		uint NumParticlesActive;
		VertexParticle * Vertices;
		short * Indices;

		static const uint MAX_PARTICLES = 8192;

		mmath::BoundingBox CurrentBoundingBox;
		mmath::BoundingBox MaxBoundingBox;

	private:
		void addParticleToVB(const Particle & p, uint firstVertexPosInBuffer);
		uint getNextFreeIndex();
		void generateParticle(Particle & p);
		void spawnParticles(uint num);

		uint mPrevFreeIndex;
		float mNumToSpawnLeft;

		float mCurrentTime;

		Particle * mParticles;

		bool maxBBoxInitialized;
	};
}